﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.Glee.Drawing;

namespace GraphViewer
{
    public partial class GraphView : Form
    {
        TimelineEntries timeLineEntries;
        Dictionary<int,Graph> savedGraphs;

        public GraphView()
        {
            InitializeComponent();
        }

        private void uxLoadFiles_Click(object sender, EventArgs e)
        {
            DialogResult result = folderBrowserDialog1.ShowDialog();
            if (result == DialogResult.OK)
                LoadFiles(folderBrowserDialog1.SelectedPath);
        }

        private void LoadFiles(string path)
        {
            timeLineEntries = new TimelineEntries();
            savedGraphs = new Dictionary<int, Graph>();
            gViewer1.Graph = new Graph("Start");
            GraphViewEntry entry;
            string[] splitter = new string[] { "\t" };

            string[] files = Directory.GetFiles(path, "Graph_*.txt");

            int i = 1;
            uxLoadProgress.Minimum = 1;
            uxLoadProgress.Maximum = files.Length;
            uxLoadProgress.Value = i;
            uxLoadProgress.Visible = true;

            foreach (var fileName in files)
            {
                uxLoadProgress.Value = i++;
                string[] lines = File.ReadAllLines(fileName);

                foreach (var line in lines)
                {
                    entry = new GraphViewEntry(line.Split(splitter, StringSplitOptions.RemoveEmptyEntries));

                    int entryTime = entry.Occured;
                    if (timeLineEntries.ContainsKey(entryTime))
                        timeLineEntries[entryTime].AddLast(entry);
                    else
                    {
                        GraphEdges edges = new GraphEdges();
                        edges.AddFirst(entry);
                        timeLineEntries.Add(entryTime, edges);
                    }
                }
            }

            uxTimeline.Minimum = 0;
            uxTimeline.Maximum = timeLineEntries.Count - 1;
            uxTimeline.Value = 0;
            uxLoadProgress.Visible = false;

            uxTime.Text = timeLineEntries.Keys[0].ToString("hh:mm:ss.fff");
        }

        private void uxBack_Click(object sender, EventArgs e)
        {
            if (uxTimeline.Value == 0)
                return;

            uxTimeline.Value = uxTimeline.Value - 1;
        }

        private void uxForward_Click(object sender, EventArgs e)
        {
            if (uxTimeline.Value == uxTimeline.Maximum)
                return;

            uxTimeline.Value = uxTimeline.Value + 1;
        }

        private void uxTimeline_ValueChanged(object sender, EventArgs e)
        {
            uxTime.Text = timeLineEntries.Keys[uxTimeline.Value].ToString();
            ShowGraph();
        }



        private void ShowGraph()
        {
            int graphName = Int32.Parse(uxTime.Text);
            Graph g;
            if (savedGraphs.ContainsKey(graphName))
            {
                g = savedGraphs[graphName];
            }
            else
            {
                g = new Graph(graphName.ToString());
                savedGraphs.Add(graphName, g);


                bool found;
                foreach (var item in timeLineEntries[Int32.Parse(uxTime.Text)])
                {
                    Edge temp = new Edge(item.NodeA, string.Empty, item.NodeB);
                    Edge real;

                    found = false;
                    foreach (var node in g.Edges)
                    {
                        if (((node.Source == temp.Source) || (node.Source == temp.Target)) &&
                           ((node.Target == temp.Target) || (node.Target == temp.Source)))
                            found = true;
                    }

                    if (!found)
                    {
                        real = (Edge)g.AddEdge(item.NodeA, item.NodeB);
                        real.Attr.ArrowHeadAtSource = ArrowStyle.None;
                        real.Attr.ArrowHeadAtTarget = ArrowStyle.None;
                    }
                }
            }           

            gViewer1.Graph = g;
        }

        private void uxProcessLog_Click(object sender, EventArgs e)
        {
            int i = 1;
            DialogResult result = folderBrowserDialog1.ShowDialog();

            if (result != DialogResult.OK)
                return;

            string path = folderBrowserDialog1.SelectedPath;

            string[] splitter = new string[] { "\t" };
            string[] files = Directory.GetFiles(path, "Logs_*.txt");

            uxLoadProgress.Minimum = 1;
            uxLoadProgress.Maximum = files.Length+2;
            uxLoadProgress.Value = i;
            uxLoadProgress.Visible = true;

            PeerPerfDataContext dc = new PeerPerfDataContext();
            PerfData data;

            Dictionary<string, DateTime> previousTimes;
            
            foreach (var file in files)  // for each file
            {
                string[] lines = File.ReadAllLines(file);
                previousTimes = new Dictionary<string, DateTime>();
                foreach (var line in lines) // for each line
                {
                    // Get the values
                    string[] values = line.Split(splitter, StringSplitOptions.RemoveEmptyEntries);

                    string source = values[1];                          // Node ID
                    DateTime current = DateTime.Parse(values[3]);       // Arrival Time
                    DateTime previous;                                  // Previous Time
                    
                    // If we've seen this node before
                    if (previousTimes.ContainsKey(source))
                    {
                        // Get prevous time
                        previous = previousTimes[source];

                        // Update the previous time to current
                        previousTimes[source] = DateTime.Parse(values[3]);
                    }
                    else
                    {
                        // set current to previous
                        previous = current;

                        // Add the current time to previous
                        previousTimes.Add(source, current);
                    }

                    // Parese the data and create the entry
                    data = new PerfData(values);

                    // Update Delta
                    data.ArrivalDelta = current.Subtract(previous).TotalMilliseconds;

                    if (data.MessageId != 1)
                        dc.PerfDatas.InsertOnSubmit(data);
                }
                
                dc.SubmitChanges();
                uxLoadProgress.Value += 1;
            }

            dc.SubmitChanges();

            uxLoadProgress.Value += 1;
            uxLoadProgress.Visible = false;
        }
    }
}
